Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
|
👋 Thanks for opening this pull request! A maintainer will review it soon. Please make sure all CI checks pass. |
There was a problem hiding this comment.
Pull request overview
This PR adds an “Invoice” column to the Billing History table so users can open/download an invoice when an invoiceUrl is available.
Changes:
- Adds an “Invoice” table column with a conditional “Download” link (or “Unavailable” state).
- Updates some table cell styling for the billing history rows.
- Modifies plan card border class logic in the upgrade plan selection UI.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| plan.highlight && | ||
| selectedPlan !== plan.id && | ||
| 'border-amber-500/30' | ||
| selectedPlan !== plan.id && | ||
| 'border-amber-500/30' |
There was a problem hiding this comment.
The amber border highlight is now applied to every non-selected plan because the plan.highlight && guard was removed. This makes all unselected plans look "highlighted" and decouples the border styling from the Most Popular badge logic below. Restore the plan.highlight condition (or otherwise tie the border class to the same highlight rule).
| {payment.invoiceUrl ? ( | ||
| <a | ||
| href={payment.invoiceUrl} | ||
| target="_blank" |
There was a problem hiding this comment.
payment.invoiceUrl is rendered directly into an href. If this value can ever be influenced by API data, a javascript:/non-http(s) URL could become a clickable XSS vector. Consider validating/normalizing the URL before rendering (e.g., only allow http/https and otherwise treat it as unavailable).
| <td className="py-4 text-right"> | ||
| {payment.invoiceUrl ? ( | ||
| <a |
There was a problem hiding this comment.
With the new invoiceUrl field, the billingHistory items are implicitly expected to have a specific shape, but the state is typed as any[]. This makes it easy to ship runtime errors (e.g., missing currency, status, invoiceUrl). Define a BillingHistoryItem type/interface (with invoiceUrl?: string) and use it for billingHistory and the map callback.
📝 WalkthroughWalkthroughAdded a new "Invoice" column to the billing history table that displays a download link when Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~4 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/Billing.tsx`:
- Around line 342-343: Prettier formatting is failing in the Billing component
around the JSX that renders the "Unavailable" span; run Prettier on
src/components/Billing.tsx to reformat the JSX (the span with className
"text-neutral-600 cursor-not-allowed inline-flex items-center gap-1 text-sm" and
the surrounding JSX blocks around lines where "Unavailable" appears, and the
similar JSX near lines 379-380) so the file conforms to project Prettier rules
and the CI pipeline will pass.
- Around line 332-345: Validate payment.invoiceUrl before rendering the anchor:
implement or call a helper (e.g., isValidInvoiceUrl) that attempts to construct
a URL object from payment.invoiceUrl and ensures url.protocol === 'https:'
(reject malformed or non-HTTPS URLs), then render the <a> only when that
validation passes and fall back to the "Unavailable" <span> otherwise; update
the conditional around payment.invoiceUrl in the Billing component to use that
validation check.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 287a8ec1-92ae-485a-bff4-8154008ae397
📒 Files selected for processing (1)
src/components/Billing.tsx
| {payment.invoiceUrl ? ( | ||
| <a | ||
| href={payment.invoiceUrl} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="text-primary-400 hover:text-primary-300 transition-colors inline-flex items-center gap-1 text-sm" | ||
| > | ||
| Download | ||
| </a> | ||
| ) : ( | ||
| <span className="text-neutral-600 cursor-not-allowed inline-flex items-center gap-1 text-sm" title="Invoice not available"> | ||
| Unavailable | ||
| </span> | ||
| )} |
There was a problem hiding this comment.
Validate payment.invoiceUrl before rendering it as a link.
On Line 334, href is populated directly from API data. If a non-HTTPS or malformed URL is returned, this can create a client-side security risk. Gate the link behind strict URL validation and show “Unavailable” when invalid.
🔒 Suggested fix
+ const getSafeInvoiceUrl = (rawUrl?: string) => {
+ if (!rawUrl) return null;
+ try {
+ const parsed = new URL(rawUrl);
+ return parsed.protocol === 'https:' ? parsed.toString() : null;
+ } catch {
+ return null;
+ }
+ };
...
- {payment.invoiceUrl ? (
+ {getSafeInvoiceUrl(payment.invoiceUrl) ? (
<a
- href={payment.invoiceUrl}
+ href={getSafeInvoiceUrl(payment.invoiceUrl)!}
target="_blank"
rel="noopener noreferrer"
className="text-primary-400 hover:text-primary-300 transition-colors inline-flex items-center gap-1 text-sm"
>
Download
</a>
) : (🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/Billing.tsx` around lines 332 - 345, Validate
payment.invoiceUrl before rendering the anchor: implement or call a helper
(e.g., isValidInvoiceUrl) that attempts to construct a URL object from
payment.invoiceUrl and ensures url.protocol === 'https:' (reject malformed or
non-HTTPS URLs), then render the <a> only when that validation passes and fall
back to the "Unavailable" <span> otherwise; update the conditional around
payment.invoiceUrl in the Billing component to use that validation check.
| <span className="text-neutral-600 cursor-not-allowed inline-flex items-center gap-1 text-sm" title="Invoice not available"> | ||
| Unavailable |
There was a problem hiding this comment.
CI is currently blocked by formatting issues.
Pipeline already reports Prettier failure; please run Prettier on this file before merge (the JSX wrapping around these changed lines is a likely contributor).
Also applies to: 379-380
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/Billing.tsx` around lines 342 - 343, Prettier formatting is
failing in the Billing component around the JSX that renders the "Unavailable"
span; run Prettier on src/components/Billing.tsx to reformat the JSX (the span
with className "text-neutral-600 cursor-not-allowed inline-flex items-center
gap-1 text-sm" and the surrounding JSX blocks around lines where "Unavailable"
appears, and the similar JSX near lines 379-380) so the file conforms to project
Prettier rules and the CI pipeline will pass.
Summary by CodeRabbit
New Features
Style